#include "PageCache.h"

PageCache PageCache::_sInst;


// 获取一个k页的span
Span* PageCache::NewSpan(size_t k)
{
    assert(k > 0 && k < NPAGES);

    // 先检查第k个桶里有没有span
    if (!_spanList[k].Empty())
    {
        return _spanList[k].PopFront();
    }

    // 检查后面的桶里有没有span，如果有可以对它进行切分
    for (size_t i = k+1; i < NPAGES; ++i)
    {
        if (!_spanList[i].Empty())
        {
            Span* nSpan = _spanList[i].PopFront();
            Span* kSpan = new Span;

            // 再nSpan的头部切一个k页下来
            // k页span返回
            // n - k页挂在对应映射的位置

            kSpan->_pageId = nSpan->_pageId;
            kSpan->_n = k;

            nSpan->_pageId += k;
            nSpan->_n -= k;

            return kSpan;
        }
    }

    // 走到这个位置说明后面没有大页的span了
    // 这时候就去堆上申请一个128页的span
    Span* bigSpan = new Span;
    void* ptr = SystemAlloc(NPAGES - 1);
    bigSpan->_freeList = ptr;
    bigSpan->_pageId = (PAGE_ID)ptr >> PAGE_SHIIFT;
    bigSpan->_n = NPAGES - 1;

    _spanList[bigSpan->_n].PushFront(bigSpan);

    return NewSpan(k);
}